package core

import (
	"math"
	"sync"
)

func (class *Class_t) Get1Improvement() float64 {
	var (
		oldNoise = class.GetNoise()
		newNoise = 0.0
	)
	for newNoise < oldNoise { //只要还在替换,那就继续

		//遍历class的每一个学生,一一替换,找到最优的替换方法
		for i1, j1 := 0, 0; i1 != -1; i1, j1 = class.Range(i1, j1) {
			for i2, j2 := 0, 0; i2 != -1; i2, j2 = class.Range(i2, j2) {
				if i1 == i2 && j1 == j2 { //重了
					continue
				}

				//交换(i1,j1)与(i2,j2),比较噪音
				class.Swap(i1, j1, i2, j2)
				newNoise = class.GetNoise()
				if newNoise < oldNoise { //更好
					oldNoise = newNoise
				} else { //更差
					class.Swap(i1, j1, i2, j2)
				}
			}
		}
	}
	return oldNoise
}

// 贪心出n个局部最优
func better(class Class_t, outch chan<- Class_t, n int, wait *sync.WaitGroup) {
	//对打乱的教室算局部最优
	var (
		bestNoise = math.MaxFloat64
		bestClass Class_t
	)
	for range n {
		class.Rand()

		//出1个局部最优
		newNoise := class.Get1Improvement()

		//比较这个局部最优与当前最佳解
		if newNoise < bestNoise {
			bestClass = class.Copy()
			bestNoise = newNoise
		}
	}
	outch <- bestClass
	wait.Done()
}

func (class *Class_t) BetterTimes(n, threadNum int) {
	results := make(chan Class_t, threadNum)
	var wait sync.WaitGroup
	wait.Add(threadNum)
	for range threadNum {
		go better(class.Copy(), results, n/threadNum, &wait)
	}

	wait.Wait()
	//关闭通道?

	var (
		bestNoise = math.MaxFloat64
		newNoise  float64
		bestClass Class_t
	)
	for t := range results {
		newNoise = t.GetNoise()
		if newNoise < bestNoise {
			bestNoise = newNoise
			bestClass = t.Copy()
		}
	}
	*class = bestClass
}
